﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.SQLite;
using System.Text;

/// <summary>
///MessageManagement 的摘要说明
/// </summary>
public class MessageManagement
{
    static MessageManagement m_Instance = new MessageManagement();

    static public MessageManagement Instance
    {
        get { return m_Instance; }
    }

    private MessageManagement()
    {
    }

    String m_DbPath = "";
    SQLiteConnection m_Conn = null;
    Object m_Lock = new Object();
    Int64 m_MaxKey = 1;
    DateTime m_MaxCreatedTime = DateTime.Now;
    Hashtable m_Listeners = new Hashtable();

    public void Initialize(HttpContextBase context)
    {
        lock (m_Lock)
        {
            m_DbPath = context.Server.MapPath("~/App_Data/message.db");
            m_Conn = new SQLiteConnection(String.Format("Data Source=\"{0}\";Pooling=False", m_DbPath));
            m_Conn.Open();

            try
            {
                SQLiteCommand cmd = new SQLiteCommand(
                    "select max(Key) as MaxKey, max(CreatedTime) as MaxCreatedTime from Message",
                    m_Conn
                );

                SQLiteDataReader reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    m_MaxKey = reader[0] == DBNull.Value ? 1 : reader.GetInt64(0);
                    m_MaxCreatedTime = reader[1] == DBNull.Value ? DateTime.Now : reader.GetDateTime(1);
                }
            }
            catch
            {
                m_Conn.Close();
                throw;
            }
        }
    }

    public void Dispose()
    {
    }

    public List<Message> Find(String receiver, String sender, Nullable<DateTime> from)
    {
        lock (m_Lock)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("select Key,Receiver,Sender,Content,CreatedTime from Message where Receiver = ?");
            if (!String.IsNullOrEmpty(sender) || sender == "*") builder.Append(" and Sender = ? ");
            if (from != null) builder.Append(" and CreatedTime > ?");
            builder.Append(" order by CreatedTime asc");

            SQLiteCommand cmd = new SQLiteCommand(builder.ToString(), m_Conn);

            cmd.Parameters.Add("Receiver", DbType.String).Value = receiver;
            if (!String.IsNullOrEmpty(sender) || sender == "*") cmd.Parameters.Add("Sender", DbType.String).Value = sender;
            if (from != null) cmd.Parameters.Add("CreatedTime", DbType.DateTime).Value = from.Value;

            List<Message> messages = new List<Message>();
            SQLiteDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleResult);
            try
            {
                while (reader.Read())
                {
                    messages.Add(new Message(reader.GetString(2), reader.GetString(1), reader.GetString(3), reader.GetDateTime(4), reader.GetInt64(0)));
                }
            }
            finally
            {
                reader.Close();
            }
            return messages;
        }
    }

    /// <summary>
    /// 插入新的消息，插入消息后将查询m_Listeners中是否有符合条件的监听器，如存在，同时将消息发送出去
    /// </summary>
    public Message NewMessage(String receiver, String sender, DateTime createdTime, String content)
    {
        lock (m_Lock)
        {
            Message message = new Message(sender, receiver, content, createdTime, ++m_MaxKey);

            SQLiteCommand cmd = new SQLiteCommand(
                "insert into Message (Receiver,Sender,Content,CreatedTime,Key) values (?,?,?,?,?)",
                m_Conn
            );
            cmd.Parameters.Add("Receiver", DbType.String).Value = message.Receiver;
            cmd.Parameters.Add("Sender", DbType.String).Value = message.Sender;
            cmd.Parameters.Add("Content", DbType.String).Value = message.Content;
            cmd.Parameters.Add("CreatedTime", DbType.DateTime).Value = message.CreatedTime;
            cmd.Parameters.Add("Key", DbType.Int64).Value = message.Key;

            cmd.ExecuteNonQuery();

            List<Message> messages = new List<Message>();
            messages.Add(message);

            if (m_Listeners.ContainsKey(receiver))
            {
                List<MessageListener> listeners = m_Listeners[receiver] as List<MessageListener>;
                List<MessageListener> removeListeners = new List<MessageListener>();
                foreach (MessageListener listener in listeners)
                {
                    if ((listener.Sender == "*" || String.Compare(listener.Sender, sender, true) == 0) &&
                        (listener.From == null || message.CreatedTime > listener.From))
                    {
                        listener.Send(messages);
                        removeListeners.Add(listener);

                        System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(listener.Complete));
                    }
                }

                foreach (MessageListener listener in removeListeners)
                {
                    //移除监听器
                    listeners.Remove(listener);
                }
            }

            return message;
        }
    }

    /// <summary>
    /// 添加消息监听器，如果查找到符合监听器条件的消息，返回false，此时不会添加监听器
    /// 如果没有查找到符合监听器条件的消息，返回true，此时监听器将被添加到m_Listeners中
    /// </summary>
    public bool AddListener(String receiver, String sender, Nullable<DateTime> from, WebIM_AsyncResult asynResult)
    {
        MessageListener listener = new MessageListener(receiver, sender, from, asynResult);
        lock (m_Lock)
        {
            if (!m_Listeners.ContainsKey(receiver))
            {
                m_Listeners.Add(receiver, new List<MessageListener>());
            }
            List<MessageListener> listeners = m_Listeners[receiver] as List<MessageListener>;

            //查找消息
            List<Message> messages = Find(receiver, sender, from);

            if (messages.Count == 0)
            {
                //插入监听器
                listeners.Add(listener);
            }
            else
            {
                //发送消息
                listener.Send(messages);
            }
            return messages.Count == 0;
        }
    }
}

/// <summary>
/// 消息监听器
/// </summary>
public class MessageListener
{
    public String Receiver, Sender;
    private WebIM_AsyncResult m_AsynResult = null;
    public Nullable<DateTime> From;

    public MessageListener(String receiver, String sender, Nullable<DateTime> from, WebIM_AsyncResult asynResult)
    {
        Receiver = receiver;
        Sender = sender;
        From = from;
        m_AsynResult = asynResult;
    }

    public void Send(List<Message> messages)
    {
        String content = Utility.RenderHashJson(
            "Messages", messages,
            "Receiver", Receiver
        );

        m_AsynResult.Write(content);
    }

    public void Complete(object data)
    {
        m_AsynResult.Complete(data);
    }
}

public class Message : IRenderJson
{
    public String Sender, Receiver, Content;
    public DateTime CreatedTime;
    public Int64 Key;

    public Message(String sender, String receiver, String content, DateTime cteatedTime, Int64 key)
    {
        Sender = sender;
        Receiver = receiver;
        Content = content;
        CreatedTime = cteatedTime;
        Key = key;
    }

    void IRenderJson.RenderJson(StringBuilder builder)
    {
        Utility.RenderHashJson(
            builder,
            "Sender", Sender,
            "Receiver", Receiver,
            "CreatedTime", CreatedTime,
            "Key", Key,
            "Content", Content
        );
    }
}